using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Collections.Concurrent;
using System.Data.Common;
using SeataNet.Core.Common;
using SeataNet.Core.Context;
using SeataNet.Core.RPC;
using SeataNet.Core.AT;
using SeataNet.Core.TCC;
using SeataNet.Core.Saga;
using SeataNet.Core.XA;
using SeataNet.Core.Monitor;
using SeataNet.Core.Transaction;

namespace SeataNet.Core.Recovery
{
    /// <summary>
    /// 事务恢复服务接口
    /// </summary>
    public interface ITransactionRecoveryService
    {
        /// <summary>
        /// 启动恢复服务
        /// </summary>
        Task StartAsync(CancellationToken cancellationToken = default);

        /// <summary>
        /// 停止恢复服务
        /// </summary>
        Task StopAsync(CancellationToken cancellationToken = default);

        /// <summary>
        /// 手动触发恢复检查
        /// </summary>
        Task TriggerRecoveryCheckAsync();

        /// <summary>
        /// 添加需要恢复的事务
        /// </summary>
        /// <param name="xid">全局事务ID</param>
        /// <param name="transactionType">事务类型</param>
        /// <param name="status">事务状态</param>
        /// <param name="createTime">创建时间</param>
        /// <param name="nextRetryTime">下次重试时间</param>
        void AddRecoveryTransaction(string xid, string transactionType, string status, DateTime createTime, DateTime nextRetryTime);

        /// <summary>
        /// 移除恢复事务
        /// </summary>
        /// <param name="xid">全局事务ID</param>
        void RemoveRecoveryTransaction(string xid);

        /// <summary>
        /// 获取恢复事务列表
        /// </summary>
        /// <returns>恢复事务列表</returns>
        List<RecoveryTransaction> GetRecoveryTransactions();

        /// <summary>
        /// 获取恢复统计信息
        /// </summary>
        /// <returns>恢复统计信息</returns>
        RecoveryStatistics GetRecoveryStatistics();
    }

    /// <summary>
    /// 默认事务恢复服务实现
    /// </summary>
    public class DefaultTransactionRecoveryService : ITransactionRecoveryService, IDisposable
    {
        private readonly ILogger<DefaultTransactionRecoveryService> _logger;
        private readonly IOptionsMonitor<RecoveryConfiguration> _configuration;
        private readonly ITransactionManager _transactionManager;
        private readonly IAtTransactionManager _atTransactionManager;
        private readonly ITccTransactionManager _tccTransactionManager;
        private readonly ISagaTransactionManager _sagaTransactionManager;
        private readonly IXaTransactionManager _xaTransactionManager;
        private readonly ITransactionMonitor _transactionMonitor;

        private readonly ConcurrentDictionary<string, RecoveryTransaction> _recoveryTransactions;
        private readonly Timer? _recoveryTimer;
        private readonly object _statisticsLock = new object();
        private RecoveryStatistics _statistics;
        private bool _disposed = false;
        private bool _isRunning = false;

        public DefaultTransactionRecoveryService(
            ILogger<DefaultTransactionRecoveryService> logger,
            IOptionsMonitor<RecoveryConfiguration> configuration,
            ITransactionManager transactionManager,
            IAtTransactionManager atTransactionManager,
            ITccTransactionManager tccTransactionManager,
            ISagaTransactionManager sagaTransactionManager,
            IXaTransactionManager xaTransactionManager,
            ITransactionMonitor transactionMonitor)
        {
            _logger = logger;
            _configuration = configuration;
            _transactionManager = transactionManager;
            _atTransactionManager = atTransactionManager;
            _tccTransactionManager = tccTransactionManager;
            _sagaTransactionManager = sagaTransactionManager;
            _xaTransactionManager = xaTransactionManager;
            _transactionMonitor = transactionMonitor;
            _recoveryTransactions = new ConcurrentDictionary<string, RecoveryTransaction>();
            _statistics = new RecoveryStatistics();

            var config = _configuration.CurrentValue;
            _recoveryTimer = new Timer(
                async _ => await PerformRecoveryCheckAsync(),
                null,
                TimeSpan.FromMinutes(config.RecoveryCheckIntervalMinutes),
                TimeSpan.FromMinutes(config.RecoveryCheckIntervalMinutes));
        }

        public async Task StartAsync(CancellationToken cancellationToken = default)
        {
            if (_isRunning)
            {
                _logger.LogDebug("Recovery service is already running");
                return;
            }

            _isRunning = true;
            _logger.LogInformation("Transaction recovery service started");

            // 加载未完成的事务
            await LoadUnfinishedTransactionsAsync(cancellationToken);

            // 执行一次恢复检查
            await PerformRecoveryCheckAsync();
        }

        public async Task StopAsync(CancellationToken cancellationToken = default)
        {
            if (!_isRunning)
            {
                _logger.LogDebug("Recovery service is not running");
                return;
            }

            _isRunning = false;
            _logger.LogInformation("Transaction recovery service stopped");
        }

        public async Task TriggerRecoveryCheckAsync()
        {
            if (_isRunning)
            {
                await PerformRecoveryCheckAsync();
            }
        }

        public void AddRecoveryTransaction(string xid, string transactionType, string status, DateTime createTime, DateTime nextRetryTime)
        {
            var recoveryTransaction = new RecoveryTransaction
            {
                Xid = xid,
                TransactionType = transactionType,
                Status = status,
                CreateTime = createTime,
                NextRetryTime = nextRetryTime,
                RetryCount = 0,
                MaxRetryCount = _configuration.CurrentValue.MaxRetryCount
            };

            _recoveryTransactions.TryAdd(xid, recoveryTransaction);

            _logger.LogDebug("Added recovery transaction, XID: {Xid}, Type: {TransactionType}, Status: {Status}", 
                xid, transactionType, status);
        }

        public void RemoveRecoveryTransaction(string xid)
        {
            if (_recoveryTransactions.TryRemove(xid, out _))
            {
                _logger.LogDebug("Removed recovery transaction, XID: {Xid}", xid);
            }
        }

        public List<RecoveryTransaction> GetRecoveryTransactions()
        {
            return _recoveryTransactions.Values.ToList();
        }

        public RecoveryStatistics GetRecoveryStatistics()
        {
            lock (_statisticsLock)
            {
                return new RecoveryStatistics
                {
                    TotalRecoveryAttempts = _statistics.TotalRecoveryAttempts,
                    SuccessfulRecoveries = _statistics.SuccessfulRecoveries,
                    FailedRecoveries = _statistics.FailedRecoveries,
                    ActiveRecoveryTransactions = _recoveryTransactions.Count,
                    LastRecoveryTime = _statistics.LastRecoveryTime
                };
            }
        }

        /// <summary>
        /// 执行恢复检查
        /// </summary>
        private async Task PerformRecoveryCheckAsync()
        {
            try
            {
                _logger.LogDebug("Performing recovery check");

                var now = DateTime.UtcNow;
                var config = _configuration.CurrentValue;
                var transactionsToRecover = _recoveryTransactions.Values
                    .Where(t => t.NextRetryTime <= now && t.RetryCount < t.MaxRetryCount)
                    .ToList();

                if (!transactionsToRecover.Any())
                {
                    _logger.LogDebug("No transactions to recover");
                    return;
                }

                _logger.LogInformation("Found {Count} transactions to recover", transactionsToRecover.Count);

                // 更新统计信息
                lock (_statisticsLock)
                {
                    _statistics.TotalRecoveryAttempts += transactionsToRecover.Count;
                    _statistics.LastRecoveryTime = now;
                }

                // 并行恢复事务
                var recoveryTasks = transactionsToRecover.Select(async transaction =>
                {
                    try
                    {
                        var success = await RecoverTransactionAsync(transaction);
                        if (success)
                        {
                            lock (_statisticsLock)
                            {
                                _statistics.SuccessfulRecoveries++;
                            }

                            // 移除已恢复的事务
                            RemoveRecoveryTransaction(transaction.Xid);
                        }
                        else
                        {
                            // 更新重试信息
                            transaction.RetryCount++;
                            transaction.NextRetryTime = now.AddMinutes(config.RecoveryRetryIntervalMinutes);

                            // 如果达到最大重试次数，标记为失败
                            if (transaction.RetryCount >= transaction.MaxRetryCount)
                            {
                                lock (_statisticsLock)
                                {
                                    _statistics.FailedRecoveries++;
                                }

                                _logger.LogError("Transaction recovery failed after max retries, XID: {Xid}", transaction.Xid);
                                RemoveRecoveryTransaction(transaction.Xid);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "Error recovering transaction, XID: {Xid}", transaction.Xid);

                        // 更新重试信息
                        transaction.RetryCount++;
                        transaction.NextRetryTime = now.AddMinutes(config.RecoveryRetryIntervalMinutes);

                        // 如果达到最大重试次数，标记为失败
                        if (transaction.RetryCount >= transaction.MaxRetryCount)
                        {
                            lock (_statisticsLock)
                            {
                                _statistics.FailedRecoveries++;
                            }

                            RemoveRecoveryTransaction(transaction.Xid);
                        }
                    }
                });

                await Task.WhenAll(recoveryTasks);

                _logger.LogDebug("Recovery check completed");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in recovery check");
            }
        }

        /// <summary>
        /// 恢复单个事务
        /// </summary>
        private async Task<bool> RecoverTransactionAsync(RecoveryTransaction transaction)
        {
            _logger.LogDebug("Recovering transaction, XID: {Xid}, Type: {TransactionType}, RetryCount: {RetryCount}", 
                transaction.Xid, transaction.TransactionType, transaction.RetryCount);

            try
            {
                // 根据事务类型选择恢复策略
                switch (transaction.TransactionType)
                {
                    case "AT":
                        return await RecoverAtTransactionAsync(transaction);
                    case "TCC":
                        return await RecoverTccTransactionAsync(transaction);
                    case "SAGA":
                        return await RecoverSagaTransactionAsync(transaction);
                    case "XA":
                        return await RecoverXaTransactionAsync(transaction);
                    default:
                        _logger.LogWarning("Unknown transaction type: {TransactionType}", transaction.TransactionType);
                        return false;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error recovering transaction, XID: {Xid}", transaction.Xid);
                return false;
            }
        }

        /// <summary>
        /// 恢复AT事务
        /// </summary>
        private async Task<bool> RecoverAtTransactionAsync(RecoveryTransaction transaction)
        {
            try
            {
                // 查询事务状态
                var status = _transactionManager.GetStatus(transaction.Xid);

                switch (status)
                {
                    case GlobalStatus.Committing:
                    case GlobalStatus.CommitRetrying:
                        // 提交事务
                        _transactionManager.Commit(transaction.Xid);
                        return true;

                    case GlobalStatus.Rollbacking:
                    case GlobalStatus.RollbackRetrying:
                        // 回滚事务
                        _transactionManager.Rollback(transaction.Xid);
                        return true;

                    case GlobalStatus.Committed:
                    case GlobalStatus.Rollbacked:
                        // 事务已完成，无需恢复
                        return true;

                    default:
                        _logger.LogWarning("Unknown AT transaction status: {Status}, XID: {Xid}", status, transaction.Xid);
                        return false;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error recovering AT transaction, XID: {Xid}", transaction.Xid);
                return false;
            }
        }

        /// <summary>
        /// 恢复TCC事务
        /// </summary>
        private async Task<bool> RecoverTccTransactionAsync(RecoveryTransaction transaction)
        {
            try
            {
                // 查询事务状态
                var context = _tccTransactionManager.GetTransactionContext(transaction.Xid);

                if (context == null)
                {
                    _logger.LogWarning("TCC transaction context not found, XID: {Xid}", transaction.Xid);
                    return false;
                }

                switch (context.Status)
                {
                    case TccTransactionStatus.Trying:
                        // 回滚事务
                        await _tccTransactionManager.RollbackAsync(transaction.Xid);
                        return true;

                    case TccTransactionStatus.Confirming:
                        // 提交事务
                        await _tccTransactionManager.CommitAsync(transaction.Xid);
                        return true;

                    case TccTransactionStatus.Confirmed:
                    case TccTransactionStatus.Canceled:
                        // 事务已完成，无需恢复
                        return true;

                    default:
                        _logger.LogWarning("Unknown TCC transaction status: {Status}, XID: {Xid}", context.Status, transaction.Xid);
                        return false;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error recovering TCC transaction, XID: {Xid}", transaction.Xid);
                return false;
            }
        }

        /// <summary>
        /// 恢复Saga事务
        /// </summary>
        private async Task<bool> RecoverSagaTransactionAsync(RecoveryTransaction transaction)
        {
            try
            {
                // 查询事务状态
                var context = _sagaTransactionManager.GetTransactionContext(transaction.Xid);

                if (context == null)
                {
                    _logger.LogWarning("Saga transaction context not found, XID: {Xid}", transaction.Xid);
                    return false;
                }

                switch (context.Status)
                {
                    case SagaTransactionStatus.Started:
                    case SagaTransactionStatus.Running:
                        // 回滚事务
                        _sagaTransactionManager.Rollback(transaction.Xid);
                        return true;

                    case SagaTransactionStatus.Succeeded:
                    case SagaTransactionStatus.Failed:
                    case SagaTransactionStatus.Compensated:
                        // 事务已完成，无需恢复
                        return true;

                    default:
                        _logger.LogWarning("Unknown Saga transaction status: {Status}, XID: {Xid}", context.Status, transaction.Xid);
                        return false;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error recovering Saga transaction, XID: {Xid}", transaction.Xid);
                return false;
            }
        }

        /// <summary>
        /// 恢复XA事务
        /// </summary>
        private async Task<bool> RecoverXaTransactionAsync(RecoveryTransaction transaction)
        {
            try
            {
                // 查询事务状态 - XA使用全局事务状态
                var status = _transactionManager.GetStatus(transaction.Xid);

                switch (status)
                {
                    case GlobalStatus.Committing:
                    case GlobalStatus.CommitRetrying:
                        // 提交事务
                        await _xaTransactionManager.CommitAsync(transaction.Xid);
                        return true;

                    case GlobalStatus.Rollbacking:
                    case GlobalStatus.RollbackRetrying:
                        // 回滚事务
                        await _xaTransactionManager.RollbackAsync(transaction.Xid);
                        return true;

                    case GlobalStatus.Committed:
                    case GlobalStatus.Rollbacked:
                        // 事务已完成，无需恢复
                        return true;

                    default:
                        _logger.LogWarning("Unknown XA transaction status: {Status}, XID: {Xid}", status, transaction.Xid);
                        return false;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error recovering XA transaction, XID: {Xid}", transaction.Xid);
                return false;
            }
        }

        /// <summary>
        /// 加载未完成的事务
        /// </summary>
        private async Task LoadUnfinishedTransactionsAsync(CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogDebug("Loading unfinished transactions");

                // 从持久化存储中加载未完成的事务
                // 实际生产环境中，应该从以下来源加载：
                // 1. undo_log表 (AT模式)
                // 2. TCC事务日志表
                // 3. Saga状态机表
                // 4. 事务协调器的全局事务记录

                // 基础实现：从事务监控器获取未完成的事务
                try
                {
                    var activeTransactions = _transactionMonitor.GetActiveTransactions();
                    _logger.LogDebug("Transaction monitor reports {Active} active transactions",
                        activeTransactions.Count);

                    // 在实际实现中，这里应该查询数据库的undo_log表
                    // 查找status != 1 (已完成) 的记录
                    // SELECT DISTINCT xid, branch_id FROM undo_log WHERE log_status = 0

                    // 然后为每个未完成的XID创建RecoveryTransaction对象
                    // 并添加到_recoveryTransactions字典中
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, "Failed to get metrics from transaction monitor");
                }

                _logger.LogDebug("Loaded {Count} unfinished transactions", _recoveryTransactions.Count);

                await Task.CompletedTask; // 保持异步签名
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error loading unfinished transactions");
            }
        }

        public void Dispose()
        {
            if (!_disposed)
            {
                _recoveryTimer?.Dispose();
                _disposed = true;
            }
        }
    }

    /// <summary>
    /// 恢复事务
    /// </summary>
    public class RecoveryTransaction
    {
        /// <summary>
        /// 全局事务ID
        /// </summary>
        public string Xid { get; set; } = string.Empty;

        /// <summary>
        /// 事务类型
        /// </summary>
        public string TransactionType { get; set; } = string.Empty;

        /// <summary>
        /// 事务状态
        /// </summary>
        public string Status { get; set; } = string.Empty;

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreateTime { get; set; }

        /// <summary>
        /// 下次重试时间
        /// </summary>
        public DateTime NextRetryTime { get; set; }

        /// <summary>
        /// 重试次数
        /// </summary>
        public int RetryCount { get; set; }

        /// <summary>
        /// 最大重试次数
        /// </summary>
        public int MaxRetryCount { get; set; }
    }

    /// <summary>
    /// 恢复统计信息
    /// </summary>
    public class RecoveryStatistics
    {
        /// <summary>
        /// 总恢复尝试次数
        /// </summary>
        public long TotalRecoveryAttempts { get; set; }

        /// <summary>
        /// 成功恢复次数
        /// </summary>
        public long SuccessfulRecoveries { get; set; }

        /// <summary>
        /// 失败恢复次数
        /// </summary>
        public long FailedRecoveries { get; set; }

        /// <summary>
        /// 活跃恢复事务数
        /// </summary>
        public int ActiveRecoveryTransactions { get; set; }

        /// <summary>
        /// 最后恢复时间
        /// </summary>
        public DateTime? LastRecoveryTime { get; set; }
    }
}